/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


package pointtest;
import java.awt.geom.*;
import java.util.ArrayList;

/**
 *
 * @author Administrator
 */
public class TPofDegreeofImportance {
    public StockPrice[] prices;
    public int priceCount,P,Q,ipindex,fl;
;
    public int[] PointLevel1;
    public int[] PointLevel;
    public int[] HuffmanTree1,HuffmanTree2,HuffmanTree3,HuffmanTree4,HuffmanTree5,HuffmanTree6,PIP,PLA,ITPs;
    public int[] Error;
    public int[] Sorting;
    ArrayList points;
    int[][] R; // root for OptimalBST
    int[][] C; // cost table OptimalBST
    double r;
   TPofDegreeofImportance(String stockid, String date1, String date2)
    {
       jdbcmysql db = new jdbcmysql();
       db.initial();
       prices = db.getStockPrice(stockid,date1,date2);
       priceCount = db.getPriceCount();
      // ConfigurePrice();
       All();
    }
   private double ErrorPiP(int i, int j) // max distance for PIP mehtod
   {
       double error = 0;
       double p1= prices[i].Price,p2=prices[j].Price;
       double n=( p2-p1)/ (j-i);
        for(int k = i+1;k<=j;k++)
        {
           double Price,p3=prices[k].Price;   
           double e = Math.abs(p1 + n *(k-i) - p3);
           if (e>error)
           {
               error = e;
               P=k;
            }
        }
       return error;
   }
   private double errorsum (int i, int j)
   {
       double error = 0;
       double p1= prices[i].Price,p2=prices[j].Price;
       double n=( p2-p1)/ (j-i);
        for(int k = i+1;k<=j;k++)
        {
           double Price,p3=prices[k].Price;
           error += Math.abs(p1 + n *(k-i) - p3);
        }
        return error;
   }
   private double ErrorCutting(int i, int j,double maxE) // sum-distance for PLA method
   {
        double error = errorsum(i,j);
        if (error>maxE)
         {  
            double small = error;
            for(int a = i+1; a <j;a++)
            {
               double e = errorsum(i,a)+errorsum(a,j);
               if (e<small)
               {
                   small = e;
                   Q=a;
                }
            }          
        }
       return error;
   }
   public void PLA()
   {
       PLA = new int [priceCount];
       ArrayList points =new ArrayList();
       points.add(0);
       points.add(priceCount-1);

       for(int i = PLA.length-1;i>0;i--)
       {
           double error = -1;
           int index =0 ;
           for(int j=0;j<points.size()-1;j++)
           {
               int t1 = Integer.parseInt (points.get(j).toString());
               int t2 = Integer.parseInt (points.get(j+1).toString());
               double p1=prices[t1].Price,p2=prices[t2].Price;
               double e = ErrorCutting(t1,t2,error);
               if(e>error)
               {
                   error = e;
                   PLA[i]=Q;
               }
            }
          int j = 0;
          for(;Integer.parseInt (points.get(j).toString())<PLA[i];j++)
          ;
       points.add(j,PLA[i]);
     //  System.out.println(PLA[i]+"\t\n");
     }
   }
   public void PIP()
   {
       PIP = new int [priceCount];
       ArrayList points =new ArrayList();
       points.add(0);
       points.add(priceCount-1);

       for(int i = PIP.length-1;i>0;i--)
       {
           double error = 0;
           int index =0 ;
           for(int j=0;j<points.size()-1;j++)
           {
               int t1 = Integer.parseInt (points.get(j).toString());
               int t2 = Integer.parseInt (points.get(j+1).toString());
               double p1=prices[t1].Price,p2=prices[t2].Price;
               double e = ErrorPiP(t1,t2);
               if(e>error)
               {
                   error = e;
                   PIP[i]=P;                  
               }              
            }               
       int j = 0;
       for(;Integer.parseInt (points.get(j).toString())<PIP[i];j++)
          ;
       points.add(j,PIP[i]);   
     }
   }
   private void ConfigurePrice()
   {
       prices = null;
       prices = new StockPrice[12];
       prices[0]= new StockPrice("0",0);prices[1]=new StockPrice("1",2);prices[2]=new StockPrice("2",0.7);
       prices[3]= new StockPrice("0",1.5);prices[4]=new StockPrice("1",1);prices[5]=new StockPrice("2",2.6);
       prices[6]= new StockPrice("0",1.7);prices[7]=new StockPrice("1",1.9);prices[8]=new StockPrice("2",0.95);
       prices[9]=new StockPrice("2",3.1); prices[10]=new StockPrice("2",2.1); prices[11]=new StockPrice("2",2.6);
       priceCount = 12;
   }
   private void OptimalBST(int[] s)
   {
        C = new int[s.length+2][s.length+1];
        R = new int[s.length+2][s.length+1];
       
       for(int i =1;i<s.length+2;i++)
       {
           C[i][i-1] = 0;
           if(i!=s.length+1)
           {
               C[i][i] = s[i - 1];
               R[i][i] = i;
           }
       }
       int minval = 0,kmin=0,sum;
       for(int d = 1;d < s.length;d++)
       {
           for (int i = 1;i<= s.length-d;i++)
           {
               int j = i+d;
               minval = 10000;
               for(int k = i; k<=j;k++)
               {
                   if (C[i][k-1]+C[k+1][j]<minval)
                   {
                       minval = C[i][k-1]+C[k+1][j];
                       kmin = k;
                   }
               }
               R[i][j] = kmin;
               sum = s[i-1];
               for(int ss = i+1;ss<=j;ss++)
                   sum +=s[ss-1];
               C[i][j] = minval+sum;
           }
       }
   }
   private void Sorting(int[] HuffmanTree)
   {
       int N  = HuffmanTree.length;
       Sorting = new int[N];
       for(int i =1;i < N-1;i++)
       {
           int j = 0;
           for (; j < N && PointLevel1[j] != HuffmanTree[i]; j++)
                 ;
           Sorting[j]=i;
      }

   }
   public void All()
   {
       getTPfromOriginal();
       HuffmanTree1=Huffman(HuffmanTree1,1);
       HuffmanTree2=Huffman(HuffmanTree2,2);
       HuffmanTree3=Huffman(HuffmanTree3,3);
       HuffmanTree4=Huffman(HuffmanTree4,4);
       HuffmanTree5= Huffman(HuffmanTree5,5);
       HuffmanTree6= Huffman(HuffmanTree6,6);
       ITPs = Huffman(ITPs,7);
       PIP();
       PLA();
   }
   public int[] Huffman(int[] HuffmanTree,int h)
   {
       
       points =new ArrayList();
       PointLevel = new int[priceCount];

       for(int i = 0;i<priceCount;i++)
       {
           PointLevel[i] = i;
       }
       HuffmanTree = new int [PointLevel1.length];
       Error = new int [HuffmanTree.length];

       for(int i = 0 ; i<PointLevel1.length;i++)
           points.add(PointLevel1[i]);

       for (int k=0;k<HuffmanTree.length;k++)
       {
           int flag = 0;
           boolean itp = false;
           double small=1000000;
           for(int i = 0; i < points.size()-2;i++)
          {
               int x1= Integer.parseInt(points.get(i).toString());
               int x2= Integer.parseInt(points.get(i+1).toString());
               int x3= Integer.parseInt(points.get(i+2).toString());
               double s = small;
               fl = i;
              if (h==1)
                   s=Error1(x1,x2,x3);
              else if(h == 2)
                   s=Error2(x1,x2,x3);
              else if(h == 3)
                   s=Error3(x1,x2,x3);
              else if(h == 4)
                   s=Error4(x1,x2,x3);
              else if(h == 5)
                   s=Error5(x1,x2,x3);
              else if (h == 6)
                   s=Error6(x1,x2,x3);
              else if (h == 7)
              {
                   if (i+3<points.size())
                   {
                       int x4= Integer.parseInt(points.get(i+3).toString());
                       s = ErrorITP(x1,x2,x3,x4);
                       itp = true;
                  }
              }
              else
                  ;
               if (s < small)
               {
                   small = s;
                   flag = i;
              }
          }
           if (itp == true)
           {
               int x4 = Integer.parseInt(points.get(flag + 3).toString());
               int x3 = Integer.parseInt(points.get(flag + 2).toString());
               int x2 = Integer.parseInt(points.get(flag + 1).toString());
               int x1 = Integer.parseInt(points.get(flag).toString());
               points.remove(flag+1);
               points.remove(flag+1);
               HuffmanTree[k] = x2;
               HuffmanTree[++k] = x3;
           }
          else if(points.size() >= 3 && itp == false)
           {

               int x3 = Integer.parseInt(points.get(flag + 2).toString());
               int x2 = Integer.parseInt(points.get(flag + 1).toString());
               int x1 = Integer.parseInt(points.get(flag).toString());

               double p1 = prices[x1].Price, p3 =prices[x3].Price, p2=prices[x2].Price;
               double c = 200;
               boolean y = false;
               double pxx = 0, pxxx=0;
               int xx=0,xxx=0;
               if(flag-1>0&&flag+3<points.size())
               {
                       xx= Integer.parseInt(points.get(flag-1).toString()); xxx = Integer.parseInt(points.get(flag+3).toString());
                       pxx = prices[xx].Price;
                       pxxx = prices[xxx].Price;
                       y = true;
               }
               if( ((p1<= p3 && p1 >= p2)))
               {
                   points.remove(flag);
                   HuffmanTree[k] = x1;
                   if(y = true&&p2>pxx)
                   {
                        if(caculate(xx,x3)<c*small)
                        {
                           points.remove(flag);
                           HuffmanTree[++k] = x2;
                       }
                   }
                    Error[k] = x1;
               }
              else  if( ( (p1>= p3 && p1 <= p2)))
               {
                   points.remove(flag);
                   HuffmanTree[k] = x1;
                   if(y = true&&p2<pxx)
                   {
                       if(caculate(xx,x3)<c*small)
                       {
                        points.remove(flag);
                        HuffmanTree[++k] = x2;
                       }
                   }
                    Error[k] = x1;
               }
               else if ((((p3 <= p2 && p3>= p1))))
               {
                   points.remove(flag + 2);
                   HuffmanTree[k] = x3;
                   if(y = true&&p2<pxxx)
                   {
                       if(caculate(x1,xxx)<c*small)
                       {
                        points.remove(flag+1);
                        HuffmanTree[++k] = x2;
                       }
                   }
                    Error[k] = x3;
               }
               else if ((((p3 >= p2 && p3 <= p1))))
               {
                   points.remove(flag + 2);
                   HuffmanTree[k] = x3;
                   if(y = true&&p2>pxxx)
                   {
                        if(caculate(x1,xxx)<c*small)
                        {
                        points.remove(flag+1);
                        HuffmanTree[++k] = x2;
                       }
                   }
                    Error[k] = x3;
               }
                else
               {
                   points.remove(flag + 1);
                   HuffmanTree[k] = x2;
                    Error[k] = x2;
               }
           }
          else
          {
               for (int i =0;i<points.size();i++)
                  HuffmanTree[k++] = Integer.parseInt(points.get(i).toString());
               k = HuffmanTree.length;
          }
       }
      Sorting(HuffmanTree);
      return HuffmanTree;
   }
   private double caculate(int xx, int x3)
   {
       double error = 0;
        for(int k = xx;k<x3;k++)
           error += Math.abs(prices[xx].Price + ( prices[x3].Price-prices[xx].Price) *((k-xx) / (x3-xx)) - prices[k].Price);
        return error; 
   }
   private double ErrorITP(int x1,int x2,int x3,int x4)
   {
        double error = 0;
        for(int k = x1;k<=x4;k++)
           error += Math.abs(prices[x1].Price + ( prices[x4].Price-prices[x1].Price) *((k-x1) / (x4-x1)) - prices[k].Price);
        return error;
   }
    private double Error1(int i, int x2,int j) // Max_PD
   {
          double pi = prices[i].Price,pj=prices[j].Price, p2 = prices[x2].Price;
        int x1 = i, x3 =j;
        if(p2>pj&&p2>pi)
        {
            if(pi>pj)
                i =x2;
            else
                j= x2;
       }
        if(p2<pj&&p2<pi)
        {
            if(pi<pj)
                i =x2;
            else
                j= x2;
       }
       double error = 0;
       for(int k = i+1;k<j;k++)
       {
          double x =  Math.abs(prices[i].Price + ( prices[j].Price-prices[i].Price) *((k-i) / (j-i)) - prices[k].Price);
          if( x > error)
          {
              error = x;
           }
       }
       return error;
   }
    private double Error2(int i,int x2,int j)//Min_TPD
   {
         double error;
         double s = 1;
         double P1 = s*prices[i].Price,P3=s*prices[j].Price,P2=s*prices[x2].Price;
         double x =   Math.min(Math.min(Math.abs(P1 + ( P3-P1) *((x2-i) / (j-i)) -P2 ),
             Math.abs(P1 + ( P2-P1) *((j-i) / (x2-i)) - P3)),
             Math.abs(P2 + ( P3-P2) *((i-x2) / (j-x2)) - P1));

         return x;
   }
   private double Error3(int i, int x2, int j)//Sum_PD
   {
         double pi = prices[i].Price,pj=prices[j].Price, p2 = prices[x2].Price;
        int x1 = i, x3 =j;
        if(p2>pj&&p2>pi)
        {
            if(pi>pj)
                i =x2;
            else
                j= x2;
       }
        if(p2<pj&&p2<pi)
        {
            if(pi<pj)
                i =x2;
            else
                j= x2;
       }
        double error = 0;
        for(int k = i;k<=j;k++)
           error += 100*Math.abs(prices[i].Price + ( prices[j].Price-prices[i].Price) *((k-i) / (j-i)) - prices[k].Price);
        return error;
   }
    private double Error4(int i, int x2,int j)//Avg_PD
    {
          double pi = prices[i].Price,pj=prices[j].Price, p2 = prices[x2].Price;
        int x1 = i, x3 =j;
        if(p2>pj&&p2>pi)
        {
            if(pi>pj)
                i =x2;
            else
                j= x2;
       }
        if(p2<pj&&p2<pi)
        {
            if(pi<pj)
                i =x2;
            else
                j= x2;
       }
        double error = 0;
        for(int k = i;k<=j;k++)
           error += 100*Math.abs(prices[i].Price + ( prices[j].Price-prices[i].Price) *((k-i) / (j-i)) - prices[k].Price);
        return 100*error/(j-i);
    }

    private double Error5(int i, int x2,int j)//N_Max_PD
    {
          double pi = prices[i].Price,pj=prices[j].Price, p2 = prices[x2].Price;
        int x1 = i, x3 =j;
        if(p2>pj&&p2>pi)
        {
            if(pi>pj)
                i =x2;
            else
                j= x2;
       }
        if(p2<pj&&p2<pi)
        {
            if(pi<pj)
                i =x2;
            else
                j= x2;
       }
        double error = 0;
       for(int k = i+1;k<j;k++)
       {
          double x =  Math.abs(prices[i].Price + ( prices[j].Price-prices[i].Price) *((k-i) / (j-i)) - prices[k].Price);
          if( x > error)
          {
              error = x;
           }
       }
       return error*(j-i);
    }
   private double Error6(int i, int x2,int j)//N_Min_TPD
   {
       double y1= prices[i].Price,y2=prices[x2].Price,y3=prices[j].Price, t=0,z1=0,z2=0,z3=0,x1=0,x22=0,x3=0;
       for(int k = i;k<=j;k++)
       {
           t = Math.abs(prices[x2].Price + ( prices[j].Price-prices[x2].Price) *((k-x2) / (j-x2)) - prices[k].Price);
           if (t>z1)
               z1=t;
       }

        for(int k = i;k<=j;k++)
       {
           t = 100*Math.abs(prices[i].Price + ( prices[x2].Price-prices[i].Price) *((k-i) / (x2-i)) - prices[k].Price);
           if (t>z2)
              z2=t;
       }
        for(int k = i;k<=j;k++)
       {
           t = 100*Math.abs(prices[i].Price + ( prices[j].Price-prices[i].Price) *((k-i) / (j-i)) - prices[k].Price);
           if (t>z3)
              z3=t;
       }

       return (j-i)*(Math.min(z1,Math.min(z2,z3)));
}

   public void getTPfromOriginal()
   {

       int CountTP=0;
       int[] storeIndex = new int[priceCount];
       if (priceCount>0)      storeIndex[0]= 0;
       int i =1;
       for(;i<priceCount-1;i++)
       {
           if((prices[i].Price>prices[i-1].Price && prices[i].Price>=prices[i+1].Price)
              ||(prices[i].Price<=prices[i-1].Price&&prices[i].Price<prices[i+1].Price))
                storeIndex[++CountTP]=i;
       }

        if (priceCount>1) storeIndex[++CountTP]=prices.length-1;

       PointLevel1= new int[CountTP];
       for(int k=0; k< CountTP;k++)
           PointLevel1[k]= storeIndex[k];
   }
   
}
